/**
 * 收支记录管理路由模块
 * 
 * 主要功能：
 * 1. 记录查询（支持多条件筛选和分页）
 * 2. 添加记录
 * 3. 编辑记录（支持部分字段更新）
 * 4. 删除记录（软删除）
 * 
 * 权限控制：
 * - 所有接口都需要JWT Token认证
 * - 查询：可查询自己拥有或加入的账本的记录
 * - 添加：账本所有者和成员都可添加
 * - 编辑：只能编辑自己添加的记录，或所有者可编辑所有记录
 * - 删除：只能删除自己添加的记录，或所有者可删除所有记录
 * 
 * @author 个人预算管理系统开发团队
 * @date 2025-10-26
 */

// ==================== 依赖导入 ====================
const express = require('express');                    // Express框架
const router = express.Router();                       // 创建路由实例
const { authenticateToken } = require('../middleware/auth'); // JWT认证中间件
const db = require('../config/database');              // 数据库连接池

// ==================== 全局中间件 ====================

/**
 * 应用认证中间件到所有路由
 */
router.use(authenticateToken);

// ==================== 获取记录列表接口 ====================

/**
 * 获取记录列表（支持筛选和分页）
 * 
 * @route GET /api/records
 * @access Private - 需要JWT Token认证
 * 
 * @description 查询用户有权访问的记录列表，支持多条件筛选和分页
 * 
 * @param {object} req.query - 查询参数
 * @param {string} req.query.book_id - 账本ID（选填）
 * @param {string} req.query.type - 类型（income/expense，选填）
 * @param {string} req.query.category - 分类（选填）
 * @param {string} req.query.start_date - 开始日期（YYYY-MM-DD，选填）
 * @param {string} req.query.end_date - 结束日期（YYYY-MM-DD，选填）
 * @param {number} req.query.page - 页码（默认1）
 * @param {number} req.query.page_size - 每页数量（默认20）
 * 
 * @returns {object} 200 - 查询成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {object} 200.data - 数据对象
 * @returns {array} 200.data.records - 记录数组
 * @returns {object} 200.data.pagination - 分页信息
 * @returns {number} 200.data.pagination.page - 当前页码
 * @returns {number} 200.data.pagination.page_size - 每页数量
 * @returns {number} 200.data.pagination.total - 总记录数
 * @returns {number} 200.data.pagination.total_pages - 总页数
 * 
 * @example
 * // 请求示例（查询账本1的支出记录，第1页）
 * GET /api/records?book_id=1&type=expense&page=1&page_size=20
 * Authorization: Bearer <token>
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "data": {
 *     "records": [
 *       {
 *         "record_id": 1,
 *         "book_id": 1,
 *         "type": "expense",
 *         "amount": 50.00,
 *         "category": "food",
 *         "date": "2025-10-26",
 *         "remark": "午餐",
 *         "book_name": "我的账本",
 *         "book_icon": "💰"
 *       }
 *     ],
 *     "pagination": {
 *       "page": 1,
 *       "page_size": 20,
 *       "total": 100,
 *       "total_pages": 5
 *     }
 *   }
 * }
 * 
 * 动态SQL构建算法：
 * 1. 基础SQL：查询有权访问的记录
 * 2. 根据查询参数动态添加WHERE条件
 * 3. 使用参数数组防止SQL注入
 * 4. 计算分页偏移量：offset = (page - 1) * page_size
 * 5. 使用LIMIT和OFFSET实现分页
 * 
 * 设计思路：
 * 1. 筛选条件都是可选的，灵活组合
 * 2. 双重排序：先按日期倒序，再按创建时间倒序
 * 3. 软删除：只查询is_deleted=0的记录
 * 4. 权限检查：只能查询自己拥有或加入的账本的记录
 * 5. 分页查询：提高性能，避免一次加载大量数据
 */
router.get('/', async (req, res) => {
    try {
        // 1. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 2. 从查询参数获取筛选条件和分页参数
        // 使用解构赋值和默认值
        const { 
            book_id,                    // 账本ID
            type,                       // 类型（income/expense）
            category,                   // 分类
            start_date,                 // 开始日期
            end_date,                   // 结束日期
            page = 1,                   // 页码（默认1）
            page_size = 20              // 每页数量（默认20）
        } = req.query;
        
        // 3. 构建基础SQL查询
        // 查询逻辑：
        //  - 只查询未删除的记录（is_deleted = 0）
        //  - 只查询有权访问的账本的记录
        //    - b.owner_user_id = ? : 我拥有的账本
        //    - EXISTS(...) : 我加入的账本
        // JOIN account_books：获取账本名称和图标
        let sql = `
            SELECT r.*, b.book_name, b.icon as book_icon
            FROM records r
            JOIN account_books b ON r.book_id = b.book_id
            WHERE r.is_deleted = 0 AND (
                b.owner_user_id = ? OR 
                EXISTS (SELECT 1 FROM book_members WHERE book_id = r.book_id AND user_id = ?)
            )
        `;
        const params = [userId, userId];
        
        // 4. 动态添加筛选条件
        // 设计思路：根据前端传入的参数，灵活组合WHERE条件
        
        // 4.1 按账本筛选
        if (book_id) {
            sql += ' AND r.book_id = ?';
            params.push(book_id);
        }
        
        // 4.2 按类型筛选（收入/支出）
        if (type) {
            sql += ' AND r.type = ?';
            params.push(type);
        }
        
        // 4.3 按分类筛选
        if (category) {
            sql += ' AND r.category = ?';
            params.push(category);
        }
        
        // 4.4 按日期范围筛选（开始日期）
        if (start_date) {
            sql += ' AND r.date >= ?';
            params.push(start_date);
        }
        
        // 4.5 按日期范围筛选（结束日期）
        if (end_date) {
            sql += ' AND r.date <= ?';
            params.push(end_date);
        }
        
        // 5. 添加排序
        // 双重排序：
        //  1. 先按日期倒序（最新的日期在前）
        //  2. 再按创建时间倒序（同一天的记录按创建时间排）
        sql += ' ORDER BY r.date DESC, r.created_at DESC';
        
        // 6. 计算分页参数
        // offset = (page - 1) * page_size
        // 例如：第2页，每页20条，offset = (2-1)*20 = 20（跳过前20条）
        const offset = (page - 1) * page_size;
        
        // 添加LIMIT和OFFSET实现分页
        sql += ' LIMIT ? OFFSET ?';
        params.push(parseInt(page_size), offset);
        
        // 7. 执行查询
        const [records] = await db.query(sql, params);
        
        // 8. 查询符合条件的总记录数（用于计算总页数）
        // 使用相同的筛选条件，但不包含分页
        let countSql = `
            SELECT COUNT(*) as total
            FROM records r
            JOIN account_books b ON r.book_id = b.book_id
            WHERE r.is_deleted = 0 AND (
                b.owner_user_id = ? OR 
                EXISTS (SELECT 1 FROM book_members WHERE book_id = r.book_id AND user_id = ?)
            )
        `;
        const countParams = [userId, userId];
        
        // 添加相同的筛选条件（只筛选book_id，其他条件影响不大）
        if (book_id) {
            countSql += ' AND r.book_id = ?';
            countParams.push(book_id);
        }
        
        // 执行计数查询
        const [countResult] = await db.query(countSql, countParams);
        const total = countResult[0].total;
        
        // 9. 返回记录列表和分页信息
        res.json({
            code: 200,
            data: {
                records,                                // 记录数组
                pagination: {
                    page: parseInt(page),               // 当前页码
                    page_size: parseInt(page_size),     // 每页数量
                    total,                              // 总记录数
                    total_pages: Math.ceil(total / page_size)  // 总页数（向上取整）
                }
            }
        });
        
    } catch (error) {
        // 10. 错误处理
        console.error('获取记录错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '获取失败', 
            error: error.message 
        });
    }
});

// ==================== 添加记录接口 ====================

/**
 * 添加收支记录
 * 
 * @route POST /api/records
 * @access Private - 需要JWT Token认证
 * 
 * @description 在指定账本中添加一条收入或支出记录
 * 
 * @param {object} req.body - 请求体
 * @param {number} req.body.book_id - 账本ID（必填）
 * @param {string} req.body.type - 类型（income/expense，必填）
 * @param {number} req.body.amount - 金额（必填，非负数）
 * @param {string} req.body.category - 分类（必填）
 * @param {string} req.body.date - 日期（YYYY-MM-DD，必填）
 * @param {string} req.body.remark - 备注（选填）
 * 
 * @returns {object} 200 - 添加成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {string} 200.message - 成功消息
 * @returns {object} 200.data - 记录数据
 * @returns {number} 200.data.record_id - 记录ID
 * @returns {string} 200.data.type - 类型
 * @returns {number} 200.data.amount - 金额
 * @returns {string} 200.data.category - 分类
 * @returns {string} 200.data.date - 日期
 * @returns {string} 200.data.remark - 备注
 * 
 * @returns {object} 400 - 参数错误
 * @returns {object} 403 - 无权访问账本
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * POST /api/records
 * Authorization: Bearer <token>
 * {
 *   "book_id": 1,
 *   "type": "expense",
 *   "amount": 50.00,
 *   "category": "food",
 *   "date": "2025-10-26",
 *   "remark": "午餐"
 * }
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "message": "添加成功",
 *   "data": {
 *     "record_id": 1,
 *     "type": "expense",
 *     "amount": 50.00,
 *     "category": "food",
 *     "date": "2025-10-26",
 *     "remark": "午餐"
 *   }
 * }
 * 
 * 设计思路：
 * 1. 验证所有必填字段，确保数据完整性
 * 2. 验证金额为非负数，防止异常数据
 * 3. 权限检查：必须是账本所有者或成员才能添加记录
 * 4. 自动记录user_id，便于追踪是谁添加的
 * 5. parseFloat确保金额为数字类型
 */
router.post('/', async (req, res) => {
    try {
        // 1. 从请求体获取记录信息
        const { book_id, type, amount, category, date, remark } = req.body;
        
        // 2. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 3. 验证必填项
        // 账本ID、类型、金额、分类、日期都是必填的
        if (!book_id || !type || !amount || !category || !date) {
            return res.status(400).json({ 
                code: 400, 
                message: '请填写完整信息' 
            });
        }
        
        // 4. 验证金额格式
        // isNaN()：检查是否不是数字
        // amount < 0：检查是否为负数
        // 设计考虑：金额必须是非负数（0也可以，如"免费午餐"）
        if (isNaN(amount) || amount < 0) {
            return res.status(400).json({ 
                code: 400, 
                message: '金额必须是非负数' 
            });
        }
        
        // 5. 权限验证：检查用户是否有权访问该账本
        // 使用UNION查询：
        //  - 第一部分：检查是否是所有者
        //  - 第二部分：检查是否是成员（role IN ('owner', 'member')）
        const [access] = await db.query(`
            SELECT 1 FROM account_books WHERE book_id = ? AND owner_user_id = ?
            UNION
            SELECT 1 FROM book_members WHERE book_id = ? AND user_id = ? AND role IN ('owner', 'member')
        `, [book_id, userId, book_id, userId]);
        
        // 如果没有查询结果，说明用户无权访问该账本
        if (access.length === 0) {
            return res.status(403).json({ 
                code: 403, 
                message: '无权访问此账本' 
            });
        }
        
        // 6. 插入记录到数据库
        // parseFloat(amount)：确保金额是浮点数类型
        // remark || ''：如果备注为空，存储空字符串
        const [result] = await db.query(`
            INSERT INTO records (user_id, book_id, type, amount, category, date, remark)
            VALUES (?, ?, ?, ?, ?, ?, ?)
        `, [userId, book_id, type, parseFloat(amount), category, date, remark || '']);
        
        // 7. 返回成功响应
        res.status(200).json({
            code: 200,
            message: '添加成功',
            data: {
                record_id: result.insertId,      // 新记录的自增ID
                type,
                amount: parseFloat(amount),      // 返回数字类型
                category,
                date,
                remark
            }
        });
        
    } catch (error) {
        // 8. 错误处理
        console.error('添加记录错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '添加失败', 
            error: error.message 
        });
    }
});

// ==================== 编辑记录接口 ====================

/**
 * 编辑收支记录
 * 
 * @route PUT /api/records/:recordId
 * @access Private - 需要JWT Token认证
 * 
 * @description 更新指定记录的信息（支持部分字段更新）
 * 
 * @param {object} req.params - 路径参数
 * @param {string} req.params.recordId - 记录ID
 * @param {object} req.body - 请求体（所有字段都是选填）
 * @param {string} req.body.type - 类型（income/expense）
 * @param {number} req.body.amount - 金额
 * @param {string} req.body.category - 分类
 * @param {string} req.body.date - 日期（YYYY-MM-DD）
 * @param {string} req.body.remark - 备注
 * 
 * @returns {object} 200 - 更新成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {string} 200.message - 成功消息
 * 
 * @returns {object} 400 - 参数错误或没有要更新的字段
 * @returns {object} 404 - 记录不存在或无权编辑
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例（只更新金额和备注）
 * PUT /api/records/1
 * Authorization: Bearer <token>
 * {
 *   "amount": 60.00,
 *   "remark": "午餐（加菜）"
 * }
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "message": "更新成功"
 * }
 * 
 * 动态UPDATE SQL构建算法：
 * 1. 检查每个字段是否在请求体中
 * 2. 如果存在，添加到updateFields数组
 * 3. 同时添加对应的值到updateParams数组
 * 4. 使用join(', ')拼接SQL：SET field1 = ?, field2 = ?
 * 5. 执行UPDATE语句
 * 
 * 设计思路：
 * 1. 支持部分字段更新（只更新传入的字段）
 * 2. 验证金额时，检查amount !== undefined（区分未传入和传入0）
 * 3. 权限灵活：自己的记录或所有者都可以编辑
 * 4. 动态SQL：避免固定更新所有字段
 */
router.put('/:recordId', async (req, res) => {
    try {
        // 1. 从路径参数获取记录ID
        const { recordId } = req.params;
        
        // 2. 从请求体获取要更新的字段
        const { type, amount, category, date, remark } = req.body;
        
        // 3. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 4. 权限验证：检查记录是否存在且有权限编辑
        // 编辑权限：
        //  - r.user_id = ? : 自己添加的记录
        //  - b.owner_user_id = ? : 账本所有者
        //  - EXISTS(...) : 账本成员（如果开放成员编辑权限）
        const [records] = await db.query(`
            SELECT r.* FROM records r
            JOIN account_books b ON r.book_id = b.book_id
            WHERE r.record_id = ? AND r.is_deleted = 0 AND (
                r.user_id = ? OR 
                b.owner_user_id = ? OR
                EXISTS (SELECT 1 FROM book_members WHERE book_id = r.book_id AND user_id = ? AND role IN ('owner', 'member'))
            )
        `, [recordId, userId, userId, userId]);
        
        // 如果查询结果为空，说明记录不存在或无权编辑
        if (records.length === 0) {
            return res.status(404).json({ 
                code: 404, 
                message: '记录不存在或无权编辑' 
            });
        }
        
        // 5. 动态构建UPDATE SQL
        // 只更新传入的字段，未传入的字段保持不变
        const updateFields = [];    // 存储字段名，如：['type = ?', 'amount = ?']
        const updateParams = [];    // 存储对应的值，如：['expense', 50.00]
        
        // 5.1 检查type字段
        if (type) {
            updateFields.push('type = ?');
            updateParams.push(type);
        }
        
        // 5.2 检查amount字段
        // 使用amount !== undefined而不是if(amount)
        // 原因：amount可能是0，if(0)为false会跳过
        if (amount !== undefined) {
            // 验证金额
            if (isNaN(amount) || amount < 0) {
                return res.status(400).json({ 
                    code: 400, 
                    message: '金额必须是非负数' 
                });
            }
            updateFields.push('amount = ?');
            updateParams.push(parseFloat(amount));
        }
        
        // 5.3 检查category字段
        if (category) {
            updateFields.push('category = ?');
            updateParams.push(category);
        }
        
        // 5.4 检查date字段
        if (date) {
            updateFields.push('date = ?');
            updateParams.push(date);
        }
        
        // 5.5 检查remark字段
        // 使用remark !== undefined，允许清空备注（传入空字符串）
        if (remark !== undefined) {
            updateFields.push('remark = ?');
            updateParams.push(remark);
        }
        
        // 6. 检查是否有要更新的字段
        if (updateFields.length === 0) {
            return res.status(400).json({ 
                code: 400, 
                message: '没有要更新的字段' 
            });
        }
        
        // 7. 添加WHERE条件的参数（recordId）
        updateParams.push(recordId);
        
        // 8. 执行UPDATE语句
        // updateFields.join(', ')：将数组拼接为字符串
        // 例如：['type = ?', 'amount = ?'] → "type = ?, amount = ?"
        // 完整SQL：UPDATE records SET type = ?, amount = ? WHERE record_id = ?
        await db.query(
            `UPDATE records SET ${updateFields.join(', ')} WHERE record_id = ?`, 
            updateParams
        );
        
        // 9. 返回成功响应
        res.json({
            code: 200,
            message: '更新成功'
        });
        
    } catch (error) {
        // 10. 错误处理
        console.error('更新记录错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '更新失败', 
            error: error.message 
        });
    }
});

// ==================== 删除记录接口 ====================

/**
 * 删除收支记录
 * 
 * @route DELETE /api/records/:recordId
 * @access Private - 需要JWT Token认证
 * 
 * @description 删除指定记录（软删除，标记为已删除而不是真正删除）
 * 
 * @param {object} req.params - 路径参数
 * @param {string} req.params.recordId - 记录ID
 * @param {object} req.user - JWT Token解析出的用户信息
 * @param {number} req.user.user_id - 用户ID
 * 
 * @returns {object} 200 - 删除成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {string} 200.message - 成功消息
 * 
 * @returns {object} 404 - 记录不存在或无权删除
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * DELETE /api/records/1
 * Authorization: Bearer <token>
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "message": "删除成功"
 * }
 * 
 * 软删除设计：
 * 1. 不真正删除数据（DELETE FROM），而是标记为已删除（UPDATE is_deleted = 1）
 * 2. 优点：
 *    - 数据可恢复（后续可实现"撤销删除"功能）
 *    - 保留审计记录
 *    - 避免外键约束问题
 * 3. 缺点：
 *    - 占用存储空间
 *    - 查询时需要过滤is_deleted=0的记录
 * 
 * 权限控制：
 * - 可以删除自己添加的记录（r.user_id = ?）
 * - 账本所有者可以删除账本中的所有记录（b.owner_user_id = ?）
 */
router.delete('/:recordId', async (req, res) => {
    try {
        // 1. 从路径参数获取记录ID
        const { recordId } = req.params;
        
        // 2. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 3. 权限验证：检查记录是否存在且有权限删除
        // 删除权限：
        //  - r.user_id = ? : 自己添加的记录
        //  - b.owner_user_id = ? : 账本所有者（可删除账本中的所有记录）
        const [records] = await db.query(`
            SELECT r.* FROM records r
            JOIN account_books b ON r.book_id = b.book_id
            WHERE r.record_id = ? AND r.is_deleted = 0 AND (
                r.user_id = ? OR 
                b.owner_user_id = ?
            )
        `, [recordId, userId, userId]);
        
        // 如果查询结果为空，说明记录不存在或无权删除
        if (records.length === 0) {
            return res.status(404).json({ 
                code: 404, 
                message: '记录不存在或无权删除' 
            });
        }
        
        // 4. 软删除：标记为已删除
        // 不使用DELETE FROM，而是UPDATE设置is_deleted = 1
        // 这样数据仍保留在数据库中，但查询时会被过滤掉
        await db.query(
            'UPDATE records SET is_deleted = 1 WHERE record_id = ?', 
            [recordId]
        );
        
        // 5. 返回成功响应
        res.json({
            code: 200,
            message: '删除成功'
        });
        
    } catch (error) {
        // 6. 错误处理
        console.error('删除记录错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '删除失败', 
            error: error.message 
        });
    }
});

// ==================== 导出路由 ====================

/**
 * 导出记录路由模块
 * 
 * @exports router - Express路由实例
 * 
 * 包含的路由：
 * - GET / - 获取记录列表（支持筛选和分页）
 * - POST / - 添加记录
 * - PUT /:recordId - 编辑记录
 * - DELETE /:recordId - 删除记录（软删除）
 * 
 * 权限说明：
 * - 所有路由都需要认证（JWT Token）
 * - 查询：可查询有权访问的账本的记录
 * - 添加：账本所有者和成员都可添加
 * - 编辑：自己的记录或所有者可编辑
 * - 删除：自己的记录或所有者可删除
 */
module.exports = router; 